package com.ming.common.liteflow.core.flow.logicflow;

import com.ming.common.liteflow.core.execption.LiteFlowELException;
import com.ming.common.liteflow.core.graph.LogicFlowData;
import com.yomahub.liteflow.builder.el.ELBus;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.builder.el.ThenELWrapper;
import com.yomahub.liteflow.builder.el.WhenELWrapper;

import java.util.*;
import java.util.stream.Collectors;

public class LogicflowElUtil {

    public static ELWrapper transform(LogicFlow flow) throws LiteFlowELException {
        List<LogicFlowData> flowDataList = LogicflowJsonUtil.getLogicFlowGroup(flow.json);
        if(flowDataList.size() > 1){
            //多起点嵌套处理
            WhenELWrapper when = ELBus.when();
            for (LogicFlowData data : flowDataList){
                LogicFlowGraphEL graphEL = LogicFlowGraphEL.getGraphEL(data);
                if(data.getNodes().size() == 1 && data.getEdges().size() == 0){
                    when.when(LogicflowExecutor.nodeToEL(data.getNodes().get(0)));
                }else{
                    when.when(logicFlow(graphEL));
                }
                graphEL.setGroupNodeProp(graphEL.getStartNode(), when);//设置分组属性
                flow.graphELList.add(graphEL);
                flow.nodeInfoList.addAll(data.getIvyCmpList());
                flow.nodeInfoList = flow.nodeInfoList.stream().distinct().collect(Collectors.toList());
            }
            return when;
        }else if(flowDataList.size() == 1){
            //单起点嵌套处理
            LogicFlowData data = flowDataList.get(0);
            LogicFlowGraphEL graphEL = LogicFlowGraphEL.getGraphEL(data);
            flow.graphELList.add(graphEL);
            flow.nodeInfoList.addAll(data.getIvyCmpList());
            flow.nodeInfoList = flow.nodeInfoList.stream().distinct().collect(Collectors.toList());
            return logicFlow(graphEL);
        }
        return null;
    }

    public static ELWrapper logicFlow(LogicFlowGraphEL graphEL) throws LiteFlowELException {
        ELWrapper wrapper = LogicflowExecutor.elWrapper(graphEL);
        //前置后置组件
        if(wrapper instanceof ThenELWrapper){
            ThenELWrapper thenELWrapper = (ThenELWrapper) wrapper;
            LogicflowExecutor.preELWrapper(thenELWrapper,graphEL);
            LogicflowExecutor.finallyELWrapper(thenELWrapper,graphEL);
        }
        return wrapper;
    }

//    public static ELWrapper logicFlowWrapper(LogicFlowGraphEL graphEL) throws LiteFlowELException {
//        //单起点嵌套处理
//        ELWrapper wrapper = ELBus.then();
//        Node startNode = graphEL.getStartNode();
//        List<Node> endNode = graphEL.getEndNode();
//        List<Node> startNodeList = graphEL.getStartNodeList();
//        if(CollUtil.isNotEmpty(startNodeList) && startNodeList.size() > 1){
//            flowMultiple(wrapper, startNodeList, null, graphEL);
//        }else if(endNode != null && endNode.size() > 1){
//            flowSingle(wrapper, startNode, null, graphEL, 0,null,null);
//        }else{
//            flowSingle(wrapper, startNode, endNode == null ? null : endNode.get(0), graphEL, 0,null,null);
//        }
//        return wrapper;
//    }
//
//    // 多起点处理
//    public static void flowMultiple(ELWrapper wrapper, List<Node> startNodeList, Node endNode, LogicFlowGraphEL graphEL) throws LiteFlowELException {
//        Node joinNode = graphEL.getJoinNode(startNodeList);
//        WhenELWrapper whenELWrapper = ELBus.when();
//        for (Node startNode : startNodeList){
//            ThenELWrapper thenELWrapper = ELBus.then();
//            flowSingle(thenELWrapper,startNode,endNode,graphEL, 0,null,null);
//            whenELWrapper.when(thenELWrapper);
//        }
//        FlowConvertELUtil.convert(wrapper,whenELWrapper);
//        if(endNode == null){
//            flowSingle(wrapper,joinNode,endNode,graphEL, 0,null,null);
//        }
//    }
//
//    // 单起点处理
//    public static void flowSingle(ELWrapper wrapper, Node currNode, Node endNode, LogicFlowGraphEL graphEL, int flag, List<Node> excludeList,List<Node> excludeNodeList) throws LiteFlowELException {
//        Map<Node, List<Node>> nodeMap = graphEL.getList();
//        if(currNode == null && endNode == null){
//            return;
//        }
//        if(graphEL.isEndNode(currNode) || graphEL.isEndNode(currNode, endNode)){
//            flowThen(wrapper,currNode,currNode,graphEL);
//            return;
//        }
//        // 多并行路径嵌套
//        List<Node> nodeList = nodeMap.get(currNode);
//        if(nodeList.size() == 1 && graphEL.getReverseList().get(nodeList.get(0)).size() > 1){
//            flowThen(wrapper,currNode,currNode,graphEL);
//            if(flag == 1){
//                flowSingle(wrapper,endNode,null,graphEL, 0,excludeList, excludeNodeList);
//            }
//            return;
//        }
//        Node forkNode = graphEL.getForkNode(currNode);
//        List<Node> forkChildList = nodeMap.get(forkNode);
//
//        if(graphEL.isCommonEdge(currNode)){
//            if(currNode == forkNode && forkChildList.size() > 1){
//                flowForks(wrapper, forkNode, endNode, graphEL, forkChildList, excludeList, excludeNodeList);
//                return;
//            }else if(graphEL.isThen(currNode,forkNode)){
//                flowThen(wrapper,currNode,forkNode,graphEL);
//            }else if(graphEL.isWhen(currNode,forkNode)){
//                flowWhen(wrapper,currNode,forkNode,graphEL,3);
//            }
//        }else{
//            if(NodeTypeEnum.SWITCH.getCode().equalsIgnoreCase(currNode.getType()) || NodeTypeEnum.SWITCH_SCRIPT.getCode().equals(currNode.getProperties().getType())){
//                flowSwitch(wrapper,currNode,currNode,graphEL,forkChildList);
//                return;
//            }else if(NodeTypeEnum.IF.getCode().equalsIgnoreCase(currNode.getType()) || NodeTypeEnum.IF_SCRIPT.getCode().equals(currNode.getProperties().getType())){
//                flowIf(wrapper,currNode,endNode,graphEL,forkChildList);
//                return;
//            }
//        }
//        flowSingle(wrapper, forkNode, endNode, graphEL, 0,excludeList, excludeNodeList);
//    }
//
//    // 分叉处理
//    public static void flowForks(ELWrapper wrapper, Node currNode, Node endNode, LogicFlowGraphEL graphEL, List<Node> forkChildList, List<Node> excludeList, List<Node> excludeNodeList) throws LiteFlowELException {
//        flowThen(wrapper,currNode,currNode,graphEL);
//        Node joinNode = graphEL.getJoinNode(forkChildList);
//
//        List<List<Node>> allPaths = graphEL.getAllPaths(currNode, joinNode, false);
//        if(CollUtil.isEmpty(allPaths)){
//            allPaths = graphEL.getAllPaths(currNode, false);
//        }
//        Map<Node, List<List<Node>>> groupedPaths1 = allPaths.stream().collect(Collectors.groupingBy(path -> path.get(path.size() - 1)));
//        Map<Node, List<List<Node>>> groupedPaths2 = allPaths.stream().collect(Collectors.groupingBy(path -> path.get(0)));
//
//        boolean isComplexPath = groupedPaths1.size() == 1 && groupedPaths1.size() == groupedPaths2.size();
//        if(joinNode != null && !isComplexPath){
//            flowMultiple(wrapper,forkChildList,joinNode,graphEL);
//            Node prevJoinNode = graphEL.prevJoinNode(joinNode);
//            if(prevJoinNode == currNode){
//                //List<List<Node>> allPaths = graphEL.getAllPaths(currNode, false);
//                Node prevSameNode = FlowConvertELUtil.getPrevSameNode(null, allPaths);
//                flowSingle(wrapper, prevSameNode, null, graphEL, 0,excludeList, excludeNodeList);
//            }
//        }else {
//            //List<List<Node>> allPaths = graphEL.getAllPaths(currNode, false);
//            //Map<Node, List<List<Node>>> groupedPaths1 = allPaths.stream().collect(Collectors.groupingBy(path -> path.get(path.size() - 1)));
//            //Map<Node, List<List<Node>>> groupedPaths2 = allPaths.stream().collect(Collectors.groupingBy(path -> path.get(0)));
//            List<Node> forkStartNodeList = FlowConvertELUtil.getPrevForkNode(currNode, groupedPaths1, graphEL);
//            if (allPaths.size() == groupedPaths1.size()) {
//                WhenELWrapper whenELWrapper = ELBus.when();
//                for (Node child : forkChildList) {
//                    ThenELWrapper thenELWrapper = ELBus.then();
//                    flowSingle(thenELWrapper, child, null, graphEL, 0, null, null);
//                    boolean isThen = graphEL.isThen(child);
//                    List<Node> nodeList = graphEL.getList().get(child);
//                    boolean hasCommonElements = FlowConvertELUtil.isPathSameNode(groupedPaths2,child);
//                    if (isThen && nodeList.size() == 1 && hasCommonElements) {
//                        flowSingle(thenELWrapper, nodeList.get(0), null, graphEL, 0, null, null);
//                    }
//                    whenELWrapper.when(thenELWrapper);
//                }
//                graphEL.setGroupNodeProp(currNode,whenELWrapper);
//                FlowConvertELUtil.convert(wrapper, whenELWrapper);
//            } else if (forkStartNodeList.size() > 1) {// 多分叉起点 有交集路径
//                WhenELWrapper whenELWrapper = ELBus.when();
//                for (Node child : forkChildList) {
//                    ThenELWrapper thenELWrapper = ELBus.then();
//                    flowSingle(thenELWrapper, child, null, graphEL, 0, null, null);
//                    boolean isThen = graphEL.isThen(child);
//                    List<Node> nodeList = graphEL.getList().get(child);
//                    if (isThen && nodeList.size() == 1) {
//                        flowSingle(thenELWrapper, nodeList.get(0), null, graphEL, 0, null, null);
//                    }
//                    whenELWrapper.when(thenELWrapper);
//                }
//                graphEL.setGroupNodeProp(currNode,whenELWrapper);
//                FlowConvertELUtil.convert(wrapper, whenELWrapper);
//            } else if (forkStartNodeList.size() == 1) {// 单分叉起点 有交集路径
//                WhenELWrapper whenELWrapper = ELBus.when();
//                for (Map.Entry<Node, List<List<Node>>> group : groupedPaths1.entrySet()){
//                    List<Node> excludeLists = groupedPaths1.entrySet().stream()
//                            .filter(entry -> !entry.getKey().equals(group.getKey()))
//                            .flatMap(entry -> entry.getValue().stream().map(subList -> subList.get(0))).distinct().collect(Collectors.toList());
//                    List<Node> includeList = group.getValue().stream().map(m -> m.get(0)).collect(Collectors.toList());
//                    if(CollUtil.isNotEmpty(includeList)){
//                        excludeLists.removeAll(includeList);
//                    }
//                    ThenELWrapper thenELWrapper2 = ELBus.then();
//                    List<Node> forkChildLists = forkChildList.stream().filter(m-> !excludeLists.contains(m)).collect(Collectors.toList());
//                    if(forkChildLists.size() == 1){
//                        flowSingle(thenELWrapper2,forkChildLists.get(0),endNode,graphEL, 0,excludeList,excludeNodeList);
//                    }else{
//                        flowMultiple(thenELWrapper2,forkChildLists,endNode,graphEL);
//                    }
//                    whenELWrapper.when(thenELWrapper2);
//                }
//                graphEL.setGroupNodeProp(currNode,whenELWrapper);
//                FlowConvertELUtil.convert(wrapper, whenELWrapper);
//            } else {
//                WhenELWrapper whenELWrapper = ELBus.when();
//                for (Node child : forkChildList) {
//                    ThenELWrapper thenELWrapper = ELBus.then();
//                    boolean isThen = graphEL.isThen(child,joinNode);
//                    if(isThen){
//                        flowThen(thenELWrapper, child, joinNode, graphEL);
//                    }else{
//                        flowSingle(thenELWrapper, child, joinNode, graphEL, 0, null, null);
//                    }
//                    whenELWrapper.when(thenELWrapper);
//                }
//                FlowConvertELUtil.convert(wrapper, whenELWrapper);
//                graphEL.setGroupNodeProp(currNode,whenELWrapper);
//                Node prevJoinNode = graphEL.prevJoinNode(joinNode);
//                if(prevJoinNode == currNode){
//                    Node prevSameNode = FlowConvertELUtil.getPrevSameNode(null, allPaths);
//                    flowSingle(wrapper, prevSameNode, null, graphEL, 0,excludeList, excludeNodeList);
//                }
//            }
//        }
//    }
//
//    // if处理
//    public static void flowIf(ELWrapper wrapper, Node startNode, Node endNode, LogicFlowGraphEL graphEL,List<Node> childList) throws LiteFlowELException {
//        List<ThenELWrapper> trueList = new ArrayList<>();
//        List<ThenELWrapper> falseList = new ArrayList<>();
//        for (Node child : childList){
//            EdgeProperties edgeProperties = graphEL.getEdgeProperties(startNode, child);
//            ThenELWrapper thenELWrapper = ELBus.then();
//            flowSingle(thenELWrapper, child, endNode, graphEL, 0,null,null);
//            if("true".equalsIgnoreCase(edgeProperties.getIfType())){
//                trueList.add(thenELWrapper);
//            }else {
//                falseList.add(thenELWrapper);
//            }
//        }
//        NodeInfoWrapper properties = startNode.getProperties();
//        int trueSize = trueList.size();
//        int falseSize = falseList.size();
//        if(trueSize > 1){
//            throw new LiteFlowELException("if组件不能有多个true节点！");
//        }else if(trueSize == 1){
//            properties.setCmpTrueOptEL(trueList.get(0));
//        }
//        if (falseSize > 1) {
//            throw new LiteFlowELException("if组件不能有多个false节点！");
//        } else if(falseSize == 1){
//            properties.setCmpFalseOptEL(falseList.get(0));
//        }
//        ELWrapper elWrapper = ELBusIf.NEW().node(properties).toELWrapper();
//        FlowConvertELUtil.convert(wrapper,elWrapper);
//        Node joinNode = graphEL.getJoinNode(startNode);
//        if(joinNode != null ){
//            flowSingle(wrapper,joinNode,endNode,graphEL, 0,null,null);
//        }
//    }
//
//    // switch处理
//    public static void flowSwitch(ELWrapper wrapper, Node startNode, Node endNode, LogicFlowGraphEL graphEL,List<Node> childList) throws LiteFlowELException {
//        List<ThenELWrapper> switchList = new ArrayList<>();
//        List<ThenELWrapper> defaultList = new ArrayList<>();
//        for (Node child : childList){
//            EdgeProperties edgeProperties = graphEL.getEdgeProperties(startNode, child);
//            if(edgeProperties != null && "default".equals(edgeProperties.getSwitchType())){
//                ThenELWrapper defaultThenELWrapper = ELBus.then();
//                defaultThenELWrapper.then(ELBusNode.NEW().node(child.getProperties()).toELWrapper());
//                defaultList.add(defaultThenELWrapper);
//                continue;
//            }
//            List<Node> currNodeList = null;
//            List<List<Node>> allPaths = graphEL.getAllPaths(startNode);
//            for (List<Node> nodeList : allPaths){
//                if(nodeList.contains(child)){
//                    currNodeList = nodeList;
//                    break;
//                }
//            }
//            currNodeList.remove(endNode);
//            Node prevNode = currNodeList.get(currNodeList.size() - 1);
//            ThenELWrapper thenELWrapper = ELBus.then();
//            if(child == prevNode){
//                flowThen(thenELWrapper, child, prevNode, graphEL);
//            }else{
//                flowSingle(thenELWrapper, child, prevNode, graphEL, 0,null,null);
//            }
//            if(edgeProperties != null){
//                if(StrUtil.isNotBlank(edgeProperties.getId())){
//                    thenELWrapper.id(edgeProperties.getId());
//                }
//                if(StrUtil.isNotBlank(edgeProperties.getTag())){
//                    thenELWrapper.tag(edgeProperties.getTag());
//                }
//            }else{
//                thenELWrapper.id(child.getProperties().getComponentId());
//            }
//            switchList.add(thenELWrapper);
//        }
//        NodeInfoWrapper properties = startNode.getProperties();
//        if(defaultList.size() > 1){
//            throw new LiteFlowELException("switch组件不能有多个default节点！");
//        } else if (defaultList.size() == 1) {
//            properties.setCmpDefaultOptEL(defaultList.get(0));
//        }
//        properties.setCmpToEL(switchList);
//        ELWrapper elWrapper = ELBusSwitch.NEW().node(properties).toELWrapper();
//        FlowConvertELUtil.convert(wrapper,elWrapper);
//    }
//
//    // 串行处理
//    public static void flowThen(ELWrapper wrapper, Node startNode, Node endNode, LogicFlowGraphEL graphEL) throws LiteFlowELException {
//        List<Node> list = FlowConvertELUtil.getStartEndNode(startNode, endNode, graphEL);
//        if(startNode != endNode){
//            list.remove(endNode);
//        }
//        FlowConvertELUtil.convert(wrapper,FlowConvertELUtil.nodeListToArray(list, graphEL));
//    }
//
//    // 并行处理
//    public static void flowWhen(ELWrapper wrapper, Node startNode, Node endNode, LogicFlowGraphEL graphEL,int excludeStartAndEnd) throws LiteFlowELException {
//        if(startNode == graphEL.getStartNode() || graphEL.isXNode(startNode)){
//            FlowConvertELUtil.convert(wrapper,ELBus.then(FlowConvertELUtil.getELWrapper(startNode,graphEL)));
//        }
//        List<List<Node>> allPaths = graphEL.getAllPaths(startNode, endNode, excludeStartAndEnd);
//        Node joinNode = graphEL.getJoinNode(startNode);
//        List<List<List<Node>>> groupList = graphEL.handlerPaths(allPaths);
//        WhenELWrapper whenELWrapper = ELBus.when();
//        for (List<List<Node>> listList : groupList){
//            if(listList.size() == 1){
//                whenELWrapper.when(ELBus.then(FlowConvertELUtil.nodeListToArray(listList.get(0),graphEL)));
//            }else{
//                ThenELWrapper thenELWrapper = ELBus.then();
//                flowSingle(thenELWrapper, listList.get(0).get(0), joinNode, graphEL, 0,null,null);
//                whenELWrapper.when(thenELWrapper);
//            }
//        }
//        graphEL.setGroupNodeProp(startNode,whenELWrapper);
//        FlowConvertELUtil.convert(wrapper,whenELWrapper);
//    }
}
